package com.fatiny.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fatiny.core.common.Config;
import com.fatiny.core.db.ExcelAssistEntity;
import com.fatiny.core.db.ExcelEntity;
import com.fatiny.core.proto.ProtocolParser;
import com.fatiny.core.proto.ProtocolStructure;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import freemarker.template.Template;

public class Printer {
	
	private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Printer.class);
	
	public static void genPojo(List<ExcelEntity> entitys) {
		for (ExcelEntity entity : entitys) {
			try {
				if (Config.genTbMap.keySet().contains(entity.getEntityName())) {
					genConverter(entity);
					genComponent(entity);
					genEntityManager(entity);
					genEntityBean(entity);
					genEntityAssistBean(entity);
					genProtocol(entity);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 根据ExcelEntity生成EntityBase
	 * @param entity
	 * @throws Exception  
	 * @return void  
	 * @date 2019年9月16日上午11:33:16
	 */
	public static void genEntityBean(ExcelEntity entity) throws Exception
	{
		Template template = FreeMarkerTemplateUtils.getTemplate("EntityBean.ftl");
		//生成路径
		String path = Config.outputPath+"/"+entity.getModuleName().toLowerCase();
		File file = new File(path);
		file.mkdirs();
		
		String filename = path + File.separator + entity.getEntityName() +"Bean" + Config.suffix;
		file = new File(filename);

		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("tablName", entity.getTablName());
		dataMap.put("entityName", entity.getEntityName());
		dataMap.put("entityBeans", entity.getEntityBeans());
		dataMap.put("primary", entity.getPrimary());
		dataMap.put("toStr", entity.getToStr());
		dataMap.put("primarys", entity.getPrimaryKeys());
		dataMap.put("moduleName", entity.getModuleName());
		
        FileOutputStream fos = new FileOutputStream(file);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
        template.process(dataMap, out);
        log.info("成功生成文件{}", filename);
	}
	
	/**
	 * 根据ExcelEntity生成AssistBean
	 * 一个entity拥有多个复制类,所以这里一对多
	 * @param entity
	 * @throws Exception  
	 * @return void  
	 * @date 2019年9月16日上午11:33:16
	 */
	public static void genEntityAssistBean(ExcelEntity entity) throws Exception
	{
		Template template = FreeMarkerTemplateUtils.getTemplate("EntityAssistBean.ftl");
		//生成路径
		String path = Config.outputPath+"/"+entity.getModuleName().toLowerCase();
		File file = new File(path);
		file.mkdirs();
		
		for (ExcelAssistEntity assistEntity : entity.getAssistEntityMap().values()) {
			
			String filename = path + File.separator + assistEntity.getEntityName() +"" + Config.suffix;
			file = new File(filename);

			Map<String, Object> dataMap = new HashMap<String, Object>();
			dataMap.put("assistEntity", assistEntity);
			dataMap.put("moduleName", entity.getModuleName());
			dataMap.put("assistEntityMap", entity.getAssistEntityMap());
			
	        FileOutputStream fos = new FileOutputStream(file);
	        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
	        template.process(dataMap, out);
	        log.info("成功生成文件{}", filename);
		}
		
	}
	
	/**
	 * 根据ExcelEntity生成EntityBase
	 * @param entity
	 * @throws Exception  
	 * @return void  
	 * @date 2019年9月16日上午11:33:16
	 */
	public static void genEntityManager(ExcelEntity entity) throws Exception
	{
		Template template = FreeMarkerTemplateUtils.getTemplate("EntityManager.ftl");
		//生成路径
		String path = Config.outputPath+"/"+entity.getModuleName().toLowerCase();
		File file = new File(path);
		file.mkdirs();
		
		String filename = path + File.separator + entity.getModuleName() +"Manager" + Config.suffix;
		file = new File(filename);

		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("moduleName", entity.getModuleName());
		
        FileOutputStream fos = new FileOutputStream(file);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
        template.process(dataMap, out);
        log.info("成功生成文件{}", filename);
	}
	
	/**
	 * 根据ExcelEntity生成Entity
	 * @param entity
	 * @throws Exception  
	 * @return void  
	 * @date 2019年9月16日上午11:33:16
	 */
	public static void genConverter(ExcelEntity entity) throws Exception
	{
		Template template = FreeMarkerTemplateUtils.getTemplate("EntityBeanConverter.ftl");
		//生成路径
		String path = Config.outputPath+"/"+entity.getModuleName().toLowerCase();
		File file = new File(path);
		file.mkdirs();
		
		String filename = path + File.separator + entity.getEntityName() +"BeanConverter" + Config.suffix;
		file = new File(filename);

		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("entityName", entity.getEntityName());
		dataMap.put("moduleName", entity.getModuleName());
		dataMap.put("entityBeans", entity.getEntityBeans());
		
        FileOutputStream fos = new FileOutputStream(file);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
        template.process(dataMap, out);
        log.info("成功生成文件{}", filename);
	}

	/**
	 * 根据ExcelEntity生成Entity 
	 * @param entity
	 * @throws Exception  
	 * @return void  
	 * @date 2019年9月16日上午11:33:16
	 */
	public static void genComponent(ExcelEntity entity) throws Exception
	{
		//EntityContorller.ftl
		Template template = FreeMarkerTemplateUtils.getTemplate("EntityComponent.ftl");
		//生成路径
		String path = Config.outputPath+"/"+entity.getModuleName().toLowerCase();
		File file = new File(path);
		file.mkdirs();
		
		String filename = path +  File.separator + entity.getEntityName()+"Component" + Config.suffix;
		file = new File(filename);

		//协议层方法获取
		List<ProtocolStructure> protoReqStructList = Lists.newArrayList();
		Map<String, ProtocolStructure> protoAckStructMap = Maps.newLinkedHashMap();
		String moduleName = Config.genTbMap.get(entity.getEntityName()).getModuleName();
		moduleName = StringUtils.firstCharUpper(moduleName);
		for (String key : ProtocolParser.protoMap.keySet()) {
			if (key.contains(moduleName) && key.startsWith("Req")) {
				protoReqStructList.add(ProtocolParser.protoMap.get(key));
				//通过req请求,获取到ack对应请求
//				String ackKey = key.replace("Req", "Res");
//				ProtocolStructure struct = ProtocolParser.protoMap.get(ackKey);
//				if (struct != null) {
//					protoAckStructMap.put(key, struct);
//				}
			}
			else if (key.contains(moduleName) && key.startsWith("Res")) {
				ProtocolStructure struct = ProtocolParser.protoMap.get(key);
				if (struct != null) {protoAckStructMap.put(key, struct);}
			}
		}
		//模板信息创建
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap.put("moduleName", entity.getModuleName());
		dataMap.put("tablName", entity.getTablName());
		dataMap.put("entityName", entity.getEntityName());
		dataMap.put("entityBeans", entity.getEntityBeans());
		dataMap.put("protoReqStructList", protoReqStructList);
		dataMap.put("protoAckStructMap", protoAckStructMap);
		
        FileOutputStream fos = new FileOutputStream(file);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
        template.process(dataMap, out);
        log.info("成功生成文件{}", filename);
	}
	
	
	/**
	 * 根据协议生成Ack 
	 * @param entity
	 * @throws Exception  
	 * @return void  
	 * @date 2019年9月16日上午11:33:16
	 */
	public static void genProtocol(ExcelEntity entity) throws Exception
	{
		//模板
		Template template = FreeMarkerTemplateUtils.getTemplate("protocol.ftl");
		
		//协议层方法获取
		List<ProtocolStructure> protoStructList = Lists.newArrayList();
		String moduleName = Config.genTbMap.get(entity.getEntityName()).getModuleName();
		moduleName = StringUtils.firstCharUpper(moduleName);
		for (String key : ProtocolParser.protoMap.keySet()) {
			if (key.contains(moduleName) && (key.startsWith("Req") || key.startsWith("Res")|| key.endsWith("Proto"))) {
				protoStructList.add(ProtocolParser.protoMap.get(key));
			}
		}
		
		//生成路径
		String path = Config.outputPath+"/"+entity.getModuleName().toLowerCase()+"/proto";
		File file = new File(path);
		file.mkdirs();
		/*
		 * 生成收集到的PB所有文件, 开始循环生成 
		 */
		for (ProtocolStructure struct : protoStructList) {
			String filename = path +  File.separator + struct.getBaseName() + Config.suffix;
			file = new File(filename);
			
			//模板信息创建
			Map<String, Object> dataMap = new HashMap<String, Object>();
			dataMap.put("entityName", entity.getEntityName());
			dataMap.put("struct", struct);
			dataMap.put("protoFields", struct.getFields());
			dataMap.put("moduleName", entity.getModuleName());
			
	        FileOutputStream fos = new FileOutputStream(file);
	        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
	        template.process(dataMap, out);
	        log.info("成功生成文件{}", filename);
		}
	}
}
